home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
dskut
/
pdisk.zip
/
PART.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-01-12
|
14KB
|
491 lines
/* program to manipulate partitions on a fixed disk.
* Written by Scott E. Garfinkle, July 1986. All rights reserved.
*
* This program will examine the partition table of a fixed disk. It will
* probably only run under a close PC XT or AT compatible running PC-DOS.
*
* usage: part [drive_number]
* where drive_number can be either 1 or 2. Default is 1.
*/
#include "part.h"
#include <errno.h>
#include <ctype.h>
#define ESC 27
extern BOOT *master_boot_rec, /* master boot record of currently selected disk */
*part_boot_rec[4]; /* boot record of each (active) logical partition */
extern DISK_TABLE far * fd_tbl;
extern PARTDATA part_data[4];
extern byte fixed_disk, /* BIOS "address" of currently selected fixed disk */
num_disks; /* number of drives attached to controller */
word sector_size; /* aka bytes per sector */
word lineno; /* current screen line */
/* 16x16 bit unsigned multiply w/32 bit result */
extern dword umul1632(word,word);
char *version="Part v2.01 11 Jan 89";
/* 2.01 -- allowed creating non-DOS partitions without formatting.
*/
main(argc,argv)
int argc;
char **argv;
{
int i, c;
if(argc > 2 || (argc>1 && argv[1][0] != '0' && argv[1][0] != '1')) {
fprintf(stderr,"Usage: part [0|1]\n");
exit(-1);
/* NOTREACHED */
}
fixed_disk = argc==1 ? DISK0 : (argv[1][0] == '0' ? DISK0 : DISK1);
erase_eos(0);
scr_pos(22,0);
printf("Partition table editor, Copyright(C) 1986, 1988 S. E. Garfinkle.");
scr_pos(23,0);
printf("All rights reserved.");
do {
sector_size = get_scr_val(14,"Enter sector size (256,512,1024,etc.):",512,256,16*1024);
} while (sector_size != 256 && (sector_size & 0x1ff));
init(); /* Will exit from init if no disks are attached */
while(1) {
scr_pos(3,0);
erase_eos(0);
pr_head();
for(i=0; i<4; i++)
if(part_data[i].sys_ind)
pr_part(i+1,master_boot_rec->ptable+i);
else
printf("%d Not active\n",i+1);
lineno = (scr_rpos() >> 8) + 1;
scr_pos(lineno+1,0);
puts(" 1. Add Partition");
puts(" 2. Change Partition");
puts(" 3. Delete Partition");
puts(" 4. Change Current Disk Parameters");
if(num_disks>1) {
i = '5';
puts(" 5. Switch Drive");
}
else
i = '4';
c=(int) get_scr_char(lineno,"Select: 0. Exit ",'0',i);
lineno += i-'0';
switch(c) {
case '.':
case '0':
clean_quit();
/* NOTREACHED */
case '1':
add_part();
break;
case '2':
mod_part();
break;
case '3':
del_part();
break;
case '4':
change_parms();
break;
case '5':
do {
sector_size = get_scr_val(14,"Enter sector size (256,512,1024,etc.):",512,256,16*1024);
} while (sector_size != 256 && (sector_size & 0x1ff));
fixed_disk = fixed_disk==DISK0 ? DISK1 : DISK0;
init();
break;
}
}
/* NOTREACHED */
}
void
add_part()
{
int i, j, k, save_line, partno, sysno, fat_size, flag, bootable;
word start, end, minstart, maxend, temp, fats_in_sector;
word uns, nsects, nheads, maxcyls, csize;
PARTITION *part;
BPB *bptr;
extern word bcode_len, _shprod;
extern char boot_code[];
maxcyls = fd_tbl->fd_ncyls-1;
nsects = fd_tbl->fd_sec_per_track;
nheads = fd_tbl->fd_heads;
_shprod = nsects * nheads;
erase_eos(lineno -= 4);
printf("Maximum cylinder number is %d.\n",maxcyls);
save_line = lineno+2;
do {
erase_eos(lineno = save_line);
partno = get_scr_char(lineno++,"Add which partition (0 to exit):",'0','4');
if(partno <'1') {
return;
/* NOTREACHED */
}
if(part_data[partno -= '1'].sys_ind) {
scr_pos(13,0);
message("Partition already active.");
continue;
/* NOTREACHED */
}
minstart = 0; /* lowest possible starting cylinder */
do {
flag = 0;
for(i=0; i<4; i++) {
PARTDATA ptemp;
ptemp = part_data[i];
if( ptemp.sys_ind &&
(ptemp.s_cylinder >= minstart && ptemp.s_cylinder-minstart < 3)
) {
minstart = ptemp.e_cylinder + 1;
flag = 1;
}
}
} while (flag);
if(minstart > maxcyls) {
scr_pos(lineno+1,0);
message("No room for a new partition on disk.");
return;
/* NOTREACHED */
}
start = get_scr_val(lineno++,"Enter starting cylinder number:",minstart,minstart,maxcyls-2);
i = (int) (0xffff/_shprod) + start - 1;
maxend = min(maxcyls,i);
do {
flag = 0;
for(i=0; i<4; i++)
if(part_data[i].sys_ind && part_data[i].e_cylinder == maxend) {
maxend = part_data[i].s_cylinder-1;
flag = 1;
}
} while (flag);
if(maxend <= minstart || maxend == -1) {
scr_pos(lineno+1,0);
message("No room for partition at selected start position.");
flag = 1;
continue;
/* NOTREACHED */
}
end = get_scr_val(lineno++,"Enter ending cylinder number:",maxend,start+2,maxend);
#ifdef DEBUG
printf("secs_per_track %u, nheads %u ", nsects, nheads);
printf(" start %d, end %d\n",start,end);
fflush(stdout);(void) getch();
#endif
for(i=flag=0; i<4; i++) {
if(!part_data[i].sys_ind)
continue;
j = part_data[i].s_cylinder;
k = part_data[i].e_cylinder;
if(start <= k && end >= j) {
flag = 1; /* blew it on this partition */
break;
}
}
if(flag) {
scr_pos(lineno+1,0);
message("New partition overlaps an old partition");
}
} while (flag);
part = &master_boot_rec->ptable[partno];
bptr = &part_boot_rec[partno]->bpb;
scr_pos(lineno+1,0);
puts(" 1. Additional DOS Volume");
puts(" 2. DOS");
puts(" 3. Extended DOS Partition");
puts(" 4. XENIX");
puts(" 5. Other");
sysno = get_scr_char(lineno," 0. Exit ",'0','4');
lineno += 6;
switch(sysno) {
case '0':
return;
/* NOTREACHED */
case '4':
sysno = XENIX_PART;
break;
case '1':
sysno = EDOS_PART;
break;
case '2':
sysno = DOS_PART;
break;
case '3':
sysno = XDOS_PART;
break;
case '5':
sysno = get_scr_val(lineno++,"Enter system ID byte:",0,0,255);
break;
}
bootable = 0;
if(sysno != EDOS_PART && sysno != XDOS_PART)
if(get_scr_char(lineno++,"Make this partition bootable? (1=yes)",'0','1') == '1')
bootable = 1;
part_data[partno].s_cylinder = start;
part_data[partno].e_cylinder = end;
part_data[partno].sys_ind = part->sys_ind = (byte) sysno;
if(bootable) {
part->boot_ind = 0x80;
for(i=0;i<4;i++)
if (i==partno)
continue;
else
if(master_boot_rec->ptable[i].boot_ind) {
master_boot_rec->ptable[i].boot_ind = 0;
boot_transfer(0,WRITE);
break;
}
}
else
part->boot_ind = 0;
part->s_head = 0;
part->e_head = nheads-1; /* and end on the last head */
uns = start ? 1 : 2; /* if first partition, save extra sec for master boot rec */
part->s_sec_cyl = put_sec_cyl(uns, start); /* sector 1 */
part->e_sec_cyl = put_sec_cyl(nsects, end);
#ifdef DEBUG
printf("\nuns %u, start %d, end %u, nsects %u, s_sec_cyl 0x%x, e_sec_cyl 0x%x\n",
uns,start,end,nsects,part->s_sec_cyl, part->e_sec_cyl);
#endif
part->rel_sect = start ? umul1632(start,_shprod) : 1L;
bptr->bytes_per_sec = sector_size;
bptr->res_sectors = 1;
bptr->nfats = 2;
bptr->media_des = 0xf8;
uns = (word) (end-start+1) * _shprod;
if(!start) /* adjust for master boot rec */
uns--;
bptr->nsectors = uns;
part->num_sects = (dword) uns;
if(sysno != EDOS_PART) {
/* that's it. write the boot records and return */
boot_transfer(0,WRITE);
boot_transfer(partno+1,WRITE);
scr_pos(lineno+2,0);
puts("Partition established. Use appropriate format utility to prep");
puts("for files.");
fflush(stdout);
sleep(5000L);
return;
/* NOTREACHED */
}
/* make an estimate of parameters to use for number of root entries, fat
* fat sectors and cluster size to use. We are somewhat somewhat conservative
* on the # of fat sectors.
*/
if(uns <= 2400) { /* "uns" is # of sectors in partition */
i = 2; /* default cluster size */
bptr->nroot_ents = 0xe0;
}
else {
i = 4;
bptr->nroot_ents = 0x200;